package com.lkd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.collect.Lists;
import com.lkd.common.VMSystem;
import com.lkd.config.TopicConfig;
import com.lkd.contract.OrderCheck;
import com.lkd.dao.OrderDao;
import com.lkd.emq.MqttProducer;
import com.lkd.entity.OrderEntity;
import com.lkd.exception.LogicException;
import com.lkd.feign.UserService;
import com.lkd.feign.VMService;
import com.lkd.service.OrderService;
import com.lkd.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private RestHighLevelClient esClient;

    @Override
    public OrderEntity getByOrderNo(String orderNo) {
        QueryWrapper<OrderEntity> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(OrderEntity::getOrderNo, orderNo);
        return this.getOne(qw);
    }


    @Override
    public Pager<OrderVO> search(Integer pageIndex, Integer pageSize, String orderNo, String openId, String startDate, String endDate) {
        return Pager.buildEmpty();
    }


    @Override
    public List<Long> getTop10Sku(Integer businessId) {

        SearchRequest searchRequest = new SearchRequest("order");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //查询条件：最近三个月

        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("update_time");
        rangeQueryBuilder.gte(LocalDateTime.now().plusMonths(-3).format(DateTimeFormatter.ISO_DATE_TIME));
        rangeQueryBuilder.lte(LocalDateTime.now().format(DateTimeFormatter.ISO_DATE_TIME));

        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(rangeQueryBuilder);

        boolQueryBuilder.must(QueryBuilders.termQuery("business_id", businessId));
        sourceBuilder.query(boolQueryBuilder);

        AggregationBuilder orderAgg = AggregationBuilders.terms("sku").field("sku_id")
                .subAggregation(AggregationBuilders.count("count").field("sku_id"))
                .order(BucketOrder.aggregation("count", false))
                .size(10);

        sourceBuilder.aggregation(orderAgg);
        searchRequest.source(sourceBuilder);

        try {
            SearchResponse searchResponse = esClient.search(searchRequest, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            if (aggregations == null) return Lists.newArrayList();

            var term = (Terms) aggregations.get("sku");
            var buckets = term.getBuckets();

            return buckets.stream().map(b -> Long.valueOf(b.getKey().toString())).collect(Collectors.toList());

        } catch (IOException e) {
            e.printStackTrace();
            return Lists.newArrayList();
        }

    }

    /**
     * 小程序创建订单
     *
     * @param payVO
     */
    @Autowired
    private VMService vmService;

    @Autowired
    private UserService userService;

    @Autowired
    private MqttProducer mqttProducer;

    @Override
    public OrderEntity creteOrder(PayVO payVO) {
        //判断是否有库存
        if (!vmService.hasCapacity(payVO.getInnerCode(), Long.valueOf(payVO.getSkuId()))) {
            throw new LogicException("该库存已售空");
        }
        //设置订单参数
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOpenId(payVO.getOpenId());   //openId 设置微信用户id
        orderEntity.setOrderNo(payVO.getInnerCode() + System.nanoTime());//设置订单编号
        orderEntity.setPayStatus(VMSystem.PAY_STATUS_NOPAY);//设置支付状态

        //根据售货机编号查询售货机信息  复制给订单对象
        VmVO vmInfo = vmService.getVMInfo(payVO.getInnerCode());
        BeanUtils.copyProperties(vmInfo, orderEntity);
        orderEntity.setAddr(vmInfo.getNodeAddr());//设置点位信息

        //根据产品id 查询产品信息  复制给订单对象
        SkuVO skuVO = vmService.getSku(payVO.getSkuId());
        BeanUtils.copyProperties(skuVO, orderEntity);
        orderEntity.setAmount(skuVO.getRealPrice());

        //设置合作商分账金额
        PartnerVO partner = userService.getPartner(vmInfo.getOwnerId());
        BigDecimal bg = new BigDecimal(skuVO.getRealPrice());  //计算分成  BigDecimal 小数 不能使用传统的+、-、*、/等算术运算符运算
        int bill = bg.multiply(new BigDecimal(partner.getRatio())).divide(new BigDecimal(100), 0, RoundingMode.HALF_UP).intValue();
        orderEntity.setBill(bill);

        this.save(orderEntity);

        //将订单放到延迟队列中，10分钟后检查支付状态！
        OrderCheck orderCheck = new OrderCheck();
        orderCheck.setOrderNo(orderEntity.getOrderNo());
        try {
            //设置延迟10分钟发送消息
            mqttProducer.send("delayed/600/" + TopicConfig.ORDER_CHECK_TOPIC, 2, orderCheck);
        } catch (JsonProcessingException e) {
            log.error("send to mq error " + e);
        }

        return orderEntity;
    }

}
